package com.ygqh.baby.service.impl;

import com.ygqh.baby.ao.DataStatus;
import com.ygqh.baby.ao.ResultSet;
import com.ygqh.baby.mapper.YgSkuCombinationMapper;
import com.ygqh.baby.model.SkuCombinationQuery;
import com.ygqh.baby.po.YgOrderDetail;
import com.ygqh.baby.po.YgSkuCombination;
import com.ygqh.baby.po.YgSkuCombinationExample;
import com.ygqh.baby.service.YgSkuCombinationService;
import org.apache.commons.collections4.CollectionUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.Assert;

import java.math.BigDecimal;
import java.util.*;
import java.util.stream.Collectors;

/**
 * @author admin
 */
@Service
public class YgSkuCombinationServiceImpl implements YgSkuCombinationService {

    @Autowired
    private YgSkuCombinationMapper ygSkuCombinationMapper;

    @Override
    public List<YgSkuCombination> find() {
        YgSkuCombinationExample example = new YgSkuCombinationExample();
        example.createCriteria().andStatusEqualTo(DataStatus.Valid.name());
        return ygSkuCombinationMapper.selectByExample(example);
    }

    @Override
    public int findCount() {
        YgSkuCombinationExample example = new YgSkuCombinationExample();
        example.createCriteria().andStatusEqualTo(DataStatus.Valid.name());
        return ygSkuCombinationMapper.countByExample(example);
    }

    @Override
    public YgSkuCombination findById(Long id) {
        return ygSkuCombinationMapper.selectByPrimaryKey(id);
    }


    @Override
    public int save(YgSkuCombination ygSkuCombination) {
        return ygSkuCombinationMapper.insertSelective(ygSkuCombination);
    }

    @Override
    public int update(YgSkuCombination ygSkuCombination) {
        return ygSkuCombinationMapper.updateByPrimaryKeySelective(ygSkuCombination);
    }


    @Override
    public List<YgSkuCombination> findListBySkuIds(Long... skuIds) {
        if (skuIds == null || skuIds.length == 0) {
            return Collections.emptyList();
        }
        YgSkuCombinationExample example = new YgSkuCombinationExample();
        example.createCriteria().andSkuIdIn(Arrays.asList(skuIds)).andStatusEqualTo(DataStatus.Valid.name());
        return ygSkuCombinationMapper.selectByExample(example);
    }

    @Override
    public List<YgOrderDetail> reassemblyOrderDetails(List<YgOrderDetail> orderDetailList) {
        if (CollectionUtils.isEmpty(orderDetailList)) {
            return orderDetailList;
        }

        Long[] skuIds = orderDetailList.stream().map(YgOrderDetail::getSkuId).toArray(Long[]::new);
        List<YgSkuCombination> list = this.findListBySkuIds(skuIds);
        if (CollectionUtils.isEmpty(list)) {
            return orderDetailList;
        }
        List<YgOrderDetail> newList = new ArrayList<>();
        Map<Long, List<YgSkuCombination>> listMap = list.stream().collect(Collectors.groupingBy(YgSkuCombination::getSkuId));
        for (YgOrderDetail detail : orderDetailList) {
            List<YgSkuCombination> skuCombinationList = listMap.get(detail.getSkuId());
            if (CollectionUtils.isNotEmpty(skuCombinationList)) {
                List<YgOrderDetail> newDetails = doAssemblyOrderDetails(detail, skuCombinationList);
                newList.addAll(newDetails);
            } else {
                newList.add(detail);
            }
        }
        return newList;

    }

    @Override
    public ResultSet<YgSkuCombination> search(SkuCombinationQuery query) {
        Map<String, Object> param = new HashMap<>();
        param.put("skuCode", query.getSkuCode());
        param.put("subSkuCode", query.getSubSkuCode());
        param.put("productName", query.getProductName());
        param.put("start", query.getStart());
        param.put("limit", query.getLimit() == 0 ? 20 : query.getLimit());

        int count = ygSkuCombinationMapper.countSuper(param);
        List<YgSkuCombination> ygSkuCombinations;
        if (count > 0) {
            ygSkuCombinations = ygSkuCombinationMapper.selectSuper(param);
        } else {
            ygSkuCombinations = Collections.emptyList();
        }
        return new ResultSet<>(count, ygSkuCombinations);
    }

    /**
     * 注意： 这里的金额有可能不平，在处理后续业务的时候需要找平差异
     *
     * @param detail             订单明细
     * @param skuCombinationList 组合装明细
     * @return List<YgOrderDetail>
     */
    private List<YgOrderDetail> doAssemblyOrderDetails(YgOrderDetail detail, List<YgSkuCombination> skuCombinationList) {
        Long quantity = skuCombinationList.stream().map(YgSkuCombination::getQuantity).reduce(0L, (a, b) -> (a + b));
        BigDecimal totalPrice = detail.getSalePrice().multiply(new BigDecimal(detail.getQuantity()));
        BigDecimal equalSharePrice = totalPrice.divide(new BigDecimal(quantity), 2, BigDecimal.ROUND_DOWN);
        BigDecimal sharedPrice = BigDecimal.ZERO;

        List<YgOrderDetail> newList = new ArrayList<>(skuCombinationList.size());
        for (int i = 0; i < skuCombinationList.size(); i++) {
            BigDecimal subSalePrice = equalSharePrice;
            YgSkuCombination skuCombination = skuCombinationList.get(i);
            BigDecimal subQuantity = new BigDecimal(skuCombination.getQuantity());
            if (i == skuCombinationList.size() - 1) {
                subSalePrice = (totalPrice.subtract(sharedPrice)).divide(subQuantity, 2, BigDecimal.ROUND_DOWN);
            }
            sharedPrice = sharedPrice.add(subSalePrice.multiply(subQuantity));
            YgOrderDetail clone = detail.clone();
            clone.setSkuCode(skuCombination.getSubSkuCode());
            clone.setProductName(skuCombination.getName());
            clone.setSalePrice(subSalePrice);
            clone.setQuantity(skuCombination.getQuantity());
            newList.add(clone);
        }

        return newList;
    }

    @Override
    public int deleteSoft(Long[] ids) {
        Assert.notEmpty(ids);
        YgSkuCombinationExample example = new YgSkuCombinationExample();
        example.createCriteria().andIdIn(Arrays.asList(ids));
        YgSkuCombination record = new YgSkuCombination();
        record.setStatus(DataStatus.Delete.name());

        return ygSkuCombinationMapper.updateByExampleSelective(record, example);
    }

    @Override
    public int deleteSoft(Long id) {
        return this.deleteSoft(new Long[]{id});
    }

    @Override
    public int saveOrUpdate(YgSkuCombination ygSkuCombination) {
        int r;
        if (ygSkuCombination.getId() != null) {
            r = this.update(ygSkuCombination);
        } else {
            r = this.save(ygSkuCombination);
        }
        return r;
    }

}

